﻿using System;
using System.Collections.Generic;
using System.Web;
using System.Web.Mvc;
using System.Linq;
using AutoMapper;
using music.domain.Services;
using NHibernate;
using NHibernate.Linq;
using NHibernate.Transform;
using music.domain.Model;
using music.web.Models.Home;
using music.web.Models.Shared;

namespace music.web.Controllers
{
	public class HomeController : BaseController
	{
		[HttpGet]
		public ActionResult Index()
		{
			using (var session = OpenSession())
			{
				var songs = LoadSongs(session, int.MinValue);

				var model = new IndexModel { Songs = songs };

				return View("Index", model);
			}
		}

		[HttpGet]
		public ActionResult SongList(int page)
		{
			using (var session = OpenSession())
			{
				var songs = LoadSongs(session, int.MinValue, page);

				if (songs.Any())
				{
					return View("SongList", songs);
				}

				return new EmptyResult();
			}
		}

		private IList<SongModel> LoadSongs(ISession session, int? rateValueLimit = null, int pageNumber = 0)
		{
			const int PAGE_SIZE = 80;
			int firstResult = PAGE_SIZE * pageNumber;

			var songs = session
				.GetNamedQuery("SongList")
				.SetMaxResults(PAGE_SIZE)
				.SetInt32("firstResult", firstResult)
				.SetGuid("userId", CurrentUserId)
				.SetParameter("rateValueLimit", rateValueLimit)
				.SetResultTransformer(Transformers.AliasToBean<SongModel>())
				.List<SongModel>();
			return songs;
		}

		[HttpGet]
		public ActionResult Info(Guid id)
		{
			using (var session = OpenSession())
			{
				// load data
				var user = session.Load<User>(CurrentUserId);
				var song = session.Get<Song>(id);
				var rate = session.Query<Rate>()
					.FirstOrDefault(r => r.Song == song && r.User == user);

				// create model
				var songModel = Mapper.Map<Song, SongModel>(song);
				songModel.RateValue = rate != null ? rate.RateValue : 0;

				var commentsModel = song.Comments
					.Select(Mapper.Map<Comments, CommentModel>)
					.ToList();

				var model = new InfoModel { Song = songModel, Comments = commentsModel };

				return View("Info", model);
			}
		}

		[HttpGet]
		public ActionResult Playlist(string key)
		{
			int rateLimit = 0;

			switch (key)
			{
				case "favorites":
					rateLimit = 1;
					break;
				case "all":
					rateLimit = int.MinValue;
					break;
			}

			using (var session = OpenSession())
			{
				var songs = LoadSongs(session, rateLimit);

				var model = new PlaylistModel { Songs = songs };

				return View("Playlist", model);
			}
		}

		[HttpGet]
		public ActionResult Upload()
		{
			return View("Upload");
		}

		[HttpGet]
		public ActionResult Help()
		{
			return View("Help");
		}

		[HttpPost]
		public ActionResult Upload(string title, string artist, string description, HttpPostedFileBase file)
		{
			using (var session = OpenSession())
			{
				var bytes = new byte[file.ContentLength];
				file.InputStream.Read(bytes, 0, bytes.Length);

				var user = session.Load<User>(CurrentUserId);

				using (var tran = session.BeginTransaction())
				{
					var song = new Song
					{
						Title = title,
						Artist = artist,
						Created = DateTime.Now,
						Description = description,
						User = user
						//Mp3 = bytes
					};

					session.Save(song);
					session.Flush();

					FileService.SaveFile(song.Id, bytes);

					tran.Commit();
				}

				return RedirectToAction("Index", "Home");
			}
		}


		public ActionResult AddComments(Guid songId, string text)
		{
			using (var session = OpenSession())
			{
				var song = session.Load<Song>(songId);
				var user = session.Load<User>(CurrentUserId);

				var comments = 
					new Comments
					{
						Created = DateTime.Now,
						User = user,
						Text = text
					};

				song.Comments.Add(comments);

				session.Save(song);
				session.Flush();
			}

			return RedirectToAction("Info", new { id = songId });
		}

		public ActionResult SetRate(Guid songId, int newRate)
		{
			using (var session = OpenSession())
			{
				var song = session.Load<Song>(songId);
				var user = session.Load<User>(CurrentUserId);

				var rate = session.Query<Rate>().FirstOrDefault(r => r.Song == song && r.User == user)
							?? new Rate { Song = song, User = user };

				rate.RateValue = newRate;

				session.Save(rate);
				session.Flush();

				string selector = newRate == 0
							? ".set-rate-empty"
							: newRate > 0
								? ".set-rate-positive"
								: ".set-rate-negative";

				return Json(new { selector });
			}
		}
	}
}
